Programmable logic devices (PLDs) are a well-known type of integrated circuit that can be programmed to perform specified logic functions. One type of PLD, the field programmable gate array (FPGA), typically includes an array of programmable tiles. These programmable tiles can include, for example, input/output blocks (IOBs), configurable logic blocks (CLBs), dedicated random access memory blocks (BRAM), multipliers, digital signal processing blocks (DSPs), processors, clock managers, delay lock loops (DLLs), and so forth.
Each programmable tile typically includes both programmable interconnect and programmable logic. The programmable interconnect typically includes a large number of interconnect lines of varying lengths interconnected by programmable interconnect points (PIPs). The programmable logic implements the logic of a user design using programmable elements that can include, for example, function generators, registers, arithmetic logic, and so forth.
The programmable interconnect and programmable logic are typically programmed by loading a stream of configuration data into internal configuration memory cells that define how the programmable elements are configured. The configuration data can be read from memory (e.g., from an external PROM) or written into the FPGA by an external device. The collective states of the individual memory cells then determine the function of the FPGA.
Another type of PLD is the Complex Programmable Logic Device, or CPLD. A CPLD includes two or more “function blocks” connected together and to input/output (I/O) resources by an interconnect switch matrix. Each function block of the CPLD includes a two-level AND/OR structure similar to those used in Programmable Logic Arrays (PLAs) and Programmable Array Logic (PAL) devices. In CPLDs, configuration data is typically stored on-chip in non-volatile memory. In some CPLDs, configuration data is stored on-chip in non-volatile memory, then downloaded to volatile memory as part of an initial configuration (programming) sequence.
For all of these programmable logic devices (PLDs), the functionality of the device is controlled by data bits provided to the device for that purpose. The data bits can be stored in volatile memory (e.g., static memory cells, as in FPGAs and some CPLDs), in non-volatile memory (e.g., FLASH memory, as in some CPLDs), or in any other type of memory cell.
Other PLDs are programmed by applying a processing layer, such as a metal layer, that programmably interconnects the various elements on the device. These PLDs are known as mask programmable devices. PLDs can also be implemented in other ways, e.g., using fuse or antifuse technology. The terms “PLD” and “programmable logic device” include but are not limited to these exemplary devices, as well as encompassing devices that are only partially programmable. For example, one type of PLD includes a combination of hard-coded transistor logic and a programmable switch fabric that programmably interconnects the hard-coded transistor logic.
Circuit designs to be implemented in PLDs are often specified in programmatic form using a Hardware Description Language (HDL) such as Verilog or VHDL. The use of an HDL allows a circuit designer to design and document an electronic system at various levels of abstraction. For example, circuit designs to be implemented in PLDs can be modeled using an HDL. HDL designs can be simulated and tested using an appropriate software-based synthesis tool.
A synthesis tool is then used to compile the abstract HDL representation of the circuit design and translate the HDL design into a less abstract implementation in terms of actual logic gates. The output of a synthesis tool can be specified in any of a variety of different forms including, but not limited to, a netlist or a bitstream. One example of a synthesis tool is the Xilinx® Synthesis Tool (XST), which is available from Xilinx® Inc. of San Jose, Calif.
To minimize design time for a user design in a PLD, it is common practice to provide pre-designed “cores” that implement common functions in the PLD. These cores can be included in a user design with little or no risk of malfunction, and can significantly speed up the design cycle. Typical cores can provide, but are not limited to, digital signal processing (DSP) functions, memories, storage elements, and math functions. Some cores include an optimally floor planned layout targeted to a specific family of PLDs. Cores can also be parameterizable, i.e., allowing the user to enter parameters to activate or change certain core functionality, whereby one or more attributes of the design are determined at compile time. In other words, values can be specified for scalable core parameters such as data path width, memory width and depth, and so forth. The design is then produced, scaled to meet the needs of the user as determined by the parameter values.
Traditionally, HDL code is used to create parameterized cores. A parameterized core is a design in which one or more attributes of the design are determined at compile time, as determined by parameters specified by the user. An attribute, whether a VHDL generic, a Verilog parameter, or any other attribute of an HDL design, can be determined using one or more HDL constant functions. Examples of circuit design attributes can include, but are not limited to, bus widths, a number of instantiations for a particular circuit component, and so forth.
An HDL constant function is a function that receives a compile-time constant as input and produces an HDL compile-time constant as an output, i.e., a circuit attribute. Thus, an HDL constant function is executed at compile time and calculates a value for a circuit attribute. The HDL constant function typically is incorporated into a synthesizable HDL design in that the HDL design is implemented in hardware. The HDL constant function itself, however, is not translated into hardware and, as such, is generally not synthesized. Instead, one or more attributes determined by the HDL constant function are used during synthesis.
In illustration, one example of an HDL constant function can be one that drives HDL generate statements to control the structure of the circuit in an effort to optimize the circuit for speed, minimal resource usage, or optimal power usage. Such an HDL constant function is executed at compile time by the synthesis tool. The values determined for the various HDL circuit attributes would then be used during synthesis of the HDL design by the synthesis tool.
As their name suggests, HDL constant functions are coded in an HDL. From the above example, it can be seen that an HDL constant function can be relatively complex. HDLs, however, are unable to utilize, or have a limited ability to employ, the types of abstractions needed to efficiently implement complex methods or data manipulations. For example, HDLs typically have limited data types and lack complicated data-type abstraction and conversion facilities. These limitations make it difficult to efficiently perform the more complex operations commonly found within HDL constant functions. In consequence, the time needed to develop and/or maintain an HDL constant function can be significant. Further, the execution of an HDL constant function can be time consuming, thereby contributing to increased synthesis times.
In short, HDL code has inherent limitations, and may not be able to solve the complex parameter sets needed to generate the most optimal implementation of a core design. Therefore, it is desirable to utilize other methods of specifying complex cores that can accommodate more complex parameters. It is further desirable to provide complex core-generation processes that can take advantage of this increased capability.